package studentprogressreport;

import java.util.Calendar;

/**
 * Class represents students entity.
 * <p>
 * The class Curriculum provides constructor and methods for getting student's
 * name and printing student's progress.
 * 
 * @author Nadejda Makarkina
 */
public class Student {
	private static final Integer START_TIME = 10;
	private static final Integer END_TIME = 18;
	private static final Integer DAY_LONG = 8;
	private static final Integer HOURS_IN_DAY = 24;
	private static final Integer MINUTES_IN_HOUR = 60;
	private static final Integer SECONDS_IN_MINUTE = 60;
	private static final Integer MILLISECONDS_IN_SECOND = 1000;
	private static final String STUDENT = "Student: %s %nCurriculum: %s "
			+ "%nCurrent date: %s %nStart date: %s %nStop date: %s"
			+ " %nCurriculum duration: %d h.";
	private static final String NOT_COMPLETED = "Training has not been completed."
			+ " It will be finished in %d h.%n";
	private static final String COMPLETED = "Training has been completed. "
			+ "%d h passed after it was finished.%n";
	private static Calendar currentDate = Calendar.getInstance();
	private final String studentName;
	private final Curriculum curriculumName;
	private final Calendar startDate;

	/**
	 * Initializes a newly created <code>Student</code> object so that it
	 * represents
	 * 
	 * @param studentName
	 *            name of the student
	 * @param curriculumName
	 *            name of the curriculum
	 * @param startDate
	 *            start date of the curriculum by the student
	 */
	public Student(String studentName, Curriculum curriculumName,
			Calendar startDate) {
		this.studentName = studentName;
		this.curriculumName = curriculumName;
		this.startDate = startDate;
	}

	/**
	 * Return name of the student.
	 * 
	 * @return name
	 */
	public String getStudentName() {
		return studentName;
	}

	/*
	 * Method calculate stop date of training using start date and course
	 * duration. Assumes that students study 8 hours a day and 7 days of the
	 * week.
	 */
	private Calendar getStopDate(Calendar startDay) {
		Calendar tmp = (Calendar) startDay.clone();
		Integer firstDayHours;
		Integer lastDayHours;
		Integer numberOfDays;
		Integer courseDuration = curriculumName.calculateCourseDuration();
		firstDayHours = END_TIME - tmp.get(Calendar.HOUR_OF_DAY);
		if (firstDayHours >= courseDuration) {
			tmp.set(Calendar.HOUR_OF_DAY, tmp.get(Calendar.HOUR_OF_DAY)
					+ courseDuration);
			return tmp;
		}
		numberOfDays = (courseDuration - firstDayHours) / DAY_LONG;
		lastDayHours = (courseDuration - firstDayHours) % DAY_LONG;
		if (lastDayHours == 0) {
			tmp.add(Calendar.DATE, numberOfDays);
			tmp.set(Calendar.HOUR_OF_DAY, END_TIME);
		} else {
			tmp.add(Calendar.DATE, numberOfDays + 1);
			tmp.set(Calendar.HOUR_OF_DAY, START_TIME + lastDayHours);
		}
		return tmp;
	}

	private void setProperTime(Calendar date) {
		// Setup minutes, second and milliseconds into 0 to count only full
		// hours
		date.set(Calendar.MINUTE, 0);
		date.set(Calendar.SECOND, 0);
		date.set(Calendar.MILLISECOND, 0);
		// If the time is after 6 PM then set up time as 6 PM,
		// if before 10 AM then set up time as 10 AM
		if (date.get(Calendar.HOUR_OF_DAY) <= START_TIME) {
			date.set(Calendar.HOUR_OF_DAY, START_TIME);
		} else if (date.get(Calendar.HOUR_OF_DAY) >= END_TIME) {
			date.set(Calendar.HOUR_OF_DAY, END_TIME);
		}
	}

	/*
	 * Method calculates difference two dates and return result in hours.
	 * Assumes that day is working day(8 hours).
	 */
	private Integer getDateDiff(Calendar date1, Calendar date2) {
		Integer tmp = ((int) ((date2.getTimeInMillis() - date1
				.getTimeInMillis()) / (HOURS_IN_DAY * MINUTES_IN_HOUR
				* SECONDS_IN_MINUTE * MILLISECONDS_IN_SECOND)));
		if (date2.get(Calendar.HOUR_OF_DAY) >= date1.get(Calendar.HOUR_OF_DAY)) {
			tmp = tmp
					* DAY_LONG
					+ (date2.get(Calendar.HOUR_OF_DAY) - date1
							.get(Calendar.HOUR_OF_DAY));
		} else {
			tmp = tmp
					* DAY_LONG
					+ (DAY_LONG + (date2.get(Calendar.HOUR_OF_DAY) - date1
							.get(Calendar.HOUR_OF_DAY)));
		}
		return tmp;
	}

	/**
	 * Method prints information about student's progress.
	 */
	public void printProgress() {
		setProperTime(startDate);
		Calendar stopDate = getStopDate(startDate);
		// currentDate.set(2013, Calendar.AUGUST, 01, 18, 0, 0);
		setProperTime(currentDate);
		System.out.println(String.format(STUDENT, studentName,
				curriculumName.getName(), currentDate.getTime(),
				startDate.getTime(), stopDate.getTime(),
				curriculumName.calculateCourseDuration()));
		if (stopDate.after(currentDate)) {
			System.out.println(String.format(NOT_COMPLETED,
					getDateDiff(currentDate, stopDate)));
		} else {
			System.out.println(String.format(COMPLETED,
					getDateDiff(stopDate, currentDate)));
		}
	}
}
